package com.anivia.system.auth.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.anivia.common.core.enums.DataHandlerBizEnum;
import com.anivia.common.core.enums.DataScopeEnum;
import com.anivia.common.core.enums.DesensitizedTypeEnum;
import com.anivia.common.core.util.AssertUtil;
import com.anivia.common.web.privoder.DataHandlerProvider;
import com.anivia.common.web.satoken.util.UserInfoUtil;
import com.anivia.system.auth.enums.ResourceBaseEnum;
import com.anivia.system.auth.enums.SwitchStatusEnum;
import com.anivia.system.auth.model.entity.*;
import com.anivia.system.auth.service.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据权限相关实现类
 *
 * @author wangj
 */
@Slf4j
@Service
public class DataHandlerProviderImpl implements DataHandlerProvider {
    @Resource
    private IRoleInfoService roleInfoService;
    @Resource
    private IRoleResourceInfoService resourceInfoService;
    @Resource
    private IUserInfoService userInfoService;
    @Resource
    private IDepartmentInfoService departmentInfoService;
    @Resource
    private IRoleFieldDesensitizationService roleFieldDesensitizationService;

    @Override
    public Set<DesensitizedTypeEnum> getDescensitizationListByLoginUser() {
        Set<Integer> roleIds = getRoleIdByLoginUser();
        if (CollUtil.isNotEmpty(roleIds)) {
            return roleFieldDesensitizationService.lambdaQuery()
                    .in(RoleFieldDesensitizationDO::getRoleId, roleIds)
                    .list()
                    .stream()
                    .map(RoleFieldDesensitizationDO::getField)
                    .collect(Collectors.toSet());

        }
        return null;
    }

    @Override
    public List<DataScopeEnum> getDataScopeByResource(Integer resourceId) {
        // 校验资源id是否正确
        ResourceBaseEnum resourceBase = ResourceBaseEnum.getByCode(resourceId);
        AssertUtil.notNull(resourceBase, "资源id错误！");

        // 获取当前用户所有角色
        Set<Integer> roleIds = getRoleIdByLoginUser();

        List<RoleResourceInfoDO> resourceList = resourceInfoService.lambdaQuery()
                .in(RoleResourceInfoDO::getRoleId, roleIds)
                .eq(RoleResourceInfoDO::getResourceId, resourceId)
                .list();
        return resourceList.stream().map(RoleResourceInfoDO::getDataScope).collect(Collectors.toList());
    }

    @Override
    public Set<Integer> getSubDeptIds(Integer deptId) {
        return departmentInfoService.lambdaQuery()
                .eq(DepartmentInfoDO::getPid, deptId)
                .list()
                .stream()
                .map(DepartmentInfoDO::getId)
                .collect(Collectors.toSet());
    }

    @Override
    public Set<Integer> getCustomDeptIds(Integer resourceId) {
        Set<Integer> roleIds = getRoleIdByLoginUser();
        if (CollUtil.isEmpty(roleIds)) {
            return null;
        }
        List<RoleResourceInfoDO> resourceList = resourceInfoService.lambdaQuery()
                .in(RoleResourceInfoDO::getRoleId, roleIds)
                .eq(RoleResourceInfoDO::getResourceId, resourceId)
                .list();

        if (CollUtil.isNotEmpty(resourceList)) {
            Set<Integer> customDeptIds = resourceList.stream().map(RoleResourceInfoDO::getCustomDeptIds).flatMap(List::stream).collect(Collectors.toSet());
            if (CollUtil.isNotEmpty(customDeptIds)) {
                return customDeptIds;
            }
        }
        return null;
    }

    @Override
    public Map<String, Set<String>> getPermissionColum(Collection<String> tableNames) {
        // TODO 字段级别权限功能暂不使用，使用时实现此方法
        return null;
    }

    @Override
    public List<String> getFieldNoPermissionExpression(DataHandlerBizEnum dataScopeBiz) {
        // TODO 字段级别权限功能暂不使用，使用时实现此方法
        List<String> noPermission = new ArrayList<>();
        noPermission.add("$.data.tags.name");
        noPermission.add("$.id");
        return noPermission;
    }

    @Override
    public Integer getDeptIdByLoginUser() {
        UserInfoDO userInfo = userInfoService.getById(UserInfoUtil.getLoginUserId());
        AssertUtil.notNull(userInfo, "用户不存在！");
        return userInfo.getDeptId();
    }

    private Set<Integer> getRoleIdByLoginUser() {
        // 获取当前用户所有角色
        List<RoleInfoDO> roleList = roleInfoService.lambdaQuery()
                .eq(RoleInfoDO::getStatus, SwitchStatusEnum.ENABLE)
                .list();
        if (CollUtil.isEmpty(roleList)) {
            return null;
        }

        return roleList.stream().map(RoleInfoDO::getId).collect(Collectors.toSet());
    }
}
